package com.zyf.service.audio;

import cn.hutool.core.io.FileUtil;
import com.zyf.service.HandleSpeechService;
import com.zyf.service.video.VedioUtils;
import com.zyf.utils.FFmpegUtils;
import it.sauronsoftware.jave.AudioAttributes;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncodingAttributes;
import javazoom.jl.player.Player;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import javax.sound.sampled.*;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;

/**
 * 截取音频
 */
public class HandleAudioService {

    private static final float VOLUMERATE = 0.69f;

    /**
     * 截取指定区间的音频
     *ffmpeg -i input.mp3 -ss start_time -to end_time -c copy output.mp3
     * @param audioFilepath
     * @param paramstartTimes
     * @param paramdurations
     */
    public void cutAudio(String audioFilepath, String paramstartTimes, String paramdurations) {
        File file = new File(audioFilepath);
        if (!file.exists()) {
            throw new RuntimeException("音频文件不存在");
        }
        String[] times = paramstartTimes.split(":");
        String[] durations = paramdurations.split(":");
        long startSec = (Integer.valueOf(times[0]) * 3600 + Integer.valueOf(times[1]) * 60 + Integer.valueOf(times[2])) * 1l;//切割开始时间，单位毫秒
        long endSec = (Integer.valueOf(durations[0]) * 3600 + Integer.valueOf(durations[1]) * 60 + Integer.valueOf(durations[2])) * 1l;// 切割持续时间，单位毫秒

        String outputpath = "";
        if (file.getName().endsWith(".wav")) {
            outputpath = audioFilepath.replace(".wav", "_cutaudio.wav");
        }
        if (file.getName().endsWith(".mp3")) {
            audioFilepath = converAudio(audioFilepath);
            outputpath = audioFilepath.replace(".wav", "_cutaudio.wav");
        }
        File outFile = new File(outputpath);
        if (outFile.exists()) {
            outFile.delete();
        }
        // startTime开始时间（以秒为单位）  duration 截取视频的时长（以秒为单位）
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        try {
            // 创建 FFmpegFrameGrabber 以读取输入音频文件
            grabber = new FFmpegFrameGrabber(audioFilepath);
            grabber.start();
            int bitrate = grabber.getAudioBitrate();
            int sampleRate = grabber.getSampleRate();
            // 创建 FFmpegFrameRecorder 以写入输出音频文件
            recorder = new FFmpegFrameRecorder(outputpath, 2);
            recorder.setAudioCodec(grabber.getAudioCodec());
            recorder.setAudioQuality(0);
            recorder.setAudioBitrate(bitrate);//比特，中等效果
            recorder.setAudioChannels(grabber.getAudioChannels());//grabber.getAudioChannels());
            recorder.setSampleRate(sampleRate);//grabber.getSampleRate());
            recorder.setAudioOption("crf", "0");
            recorder.setFormat("wav");
            recorder.start();
            //这个顺序要在后面
            Frame f;
            int total = 0;
            //计算音频样本帧的数量
            while ((f = grabber.grabSamples()) != null) {
                total++;
            }
            //计算总时长
            long durationInSec = grabber.getFormatContext().duration() / 1000000;
            //设置要剪辑掉的 倒数50秒--60秒
            //按比例计算开始录入的帧
            int startFrameNum = getStartOrEndFrameNumber(startSec, durationInSec, total);
            int endSecFN = getStartOrEndFrameNumber(endSec, durationInSec, total);
            //输出剪辑的开始时间，时长，总共帧数量，开始记录的帧位置
//			    System.out.println("Start second at {}'s,the duration is {}'s,Total Frame - {},Start frame number - {}", startSec,
//			    durationInSec, total, startFrameNum);
            int i = 0;
            //再次读取
            grabber.restart();
            while ((f = grabber.grabSamples()) != null) {
                //略过不需要记录的帧，只从需要的帧位置开始记录
                if (i >= startFrameNum && i <= endSecFN) {
                    recorder.record(f);
                }
                i++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (recorder != null) {
                    recorder.stop();
                    recorder.release();
                }
                if (grabber != null) {
                    grabber.stop();
                    grabber.release();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 截取指定区间的音频
     *ffmpeg -i input.mp3 -ss start_time -to end_time -c copy output.mp3
     * @param audioFilepath
     * @param paramstartTimes
     * @param paramdurations
     */
    public String cutAudioByFFmpeg(String audioFilepath, String paramstartTimes, String paramdurations) throws Exception {
        File file = new File(audioFilepath);
        if (!file.exists()) {
            throw new RuntimeException("音频文件不存在");
        }
        String fileName=file.getName();
        String finalPath=audioFilepath.replace(fileName,"cutaudio.wav");
        //生成str字幕文件
        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(audioFilepath);
        commands.add("-ss");
        commands.add(paramstartTimes);
        commands.add("-to");
        commands.add(paramdurations);
        commands.add("-c");
        commands.add("copy");
        commands.add(finalPath);

        String result = FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(result);
        return finalPath;
    }

    /**
     * 截取起始位置到指定长度的音频
     *
     * @param audioFilepath
     * @param type
     */
    public String cutAudioByStart(String audioFilepath, long endSec, String type) {
        long startSec = 0 * 1l;//切割开始时间，单位毫秒
        //统一转为wav无损模式
        File srcaudioFile = new File(audioFilepath);
        if (srcaudioFile.getName().endsWith(".mp3")) {
            audioFilepath = converAudio(audioFilepath);
        }
        String outputpath = audioFilepath.replace(".wav", "_cutaudio.wav");
        File outFile = new File(outputpath);
        if (outFile.exists()) {
            outFile.delete();
        }
        // startTime开始时间（以秒为单位）
        //duration 截取视频的时长（以秒为单位）
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        try {
            // 创建 FFmpegFrameGrabber 以读取输入音频文件
            grabber = new FFmpegFrameGrabber(audioFilepath);
            grabber.start();
            int bitrate = grabber.getAudioBitrate();
            int sampleRate = grabber.getSampleRate();
            // 创建 FFmpegFrameRecorder 以写入输出音频文件
            recorder = new FFmpegFrameRecorder(outputpath, 2);
            recorder.setAudioCodec(grabber.getAudioCodec());
            recorder.setAudioQuality(0);
            recorder.setAudioBitrate(bitrate);//比特，中等效果
            recorder.setAudioChannels(grabber.getAudioChannels());//grabber.getAudioChannels());
            recorder.setSampleRate(sampleRate);//grabber.getSampleRate());
            recorder.setAudioOption("crf", "0");
            recorder.setFormat(type);
            recorder.start();
            //这个顺序要在后面
            Frame f;
            int total = 0;
            //计算音频样本帧的数量
            while ((f = grabber.grabSamples()) != null) {
                total++;
            }
            //计算总时长
            long durationInSec = grabber.getFormatContext().duration() / 1000000;
            //设置要剪辑掉的 倒数50秒--60秒
            //按比例计算开始录入的帧
            int startFrameNum = getStartOrEndFrameNumber(startSec, durationInSec, total);
            int endSecFN = getStartOrEndFrameNumber(endSec, durationInSec, total);
            //输出剪辑的开始时间，时长，总共帧数量，开始记录的帧位置
//			    System.out.println("Start second at {}'s,the duration is {}'s,Total Frame - {},Start frame number - {}", startSec,
//			    durationInSec, total, startFrameNum);
            int i = 0;
            //再次读取
            grabber.restart();
            while ((f = grabber.grabSamples()) != null) {
                //略过不需要记录的帧，只从需要的帧位置开始记录
                if (i >= startFrameNum && i < endSecFN) {
                    recorder.record(f);
                }
                i++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (recorder != null) {
                    recorder.stop();
                    recorder.release();
                }
                if (grabber != null) {
                    grabber.stop();
                    grabber.release();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return outputpath;
    }

    public static int getStartOrEndFrameNumber(long startOrEndAtSecond, long durationInSecond, int totalFrame) {
        if (startOrEndAtSecond > durationInSecond)
            return (int) durationInSecond;
        double percent = startOrEndAtSecond / (double) durationInSecond;
        return (int) Math.round(totalFrame * percent);
    }

    /**
     * 音频转换   ffmpeg -i input.m4a -c:a pcm_s16le output.wav
     */
    public String converAudio(String audioFilePath) {
        File inaudioFile = new File(audioFilePath);
        if (!inaudioFile.exists()) {
            throw new RuntimeException("音频文件不存在");
        }
        String filename = inaudioFile.getName();
        if (filename.contains("mp3")) {//默认转wav
            String outFilePath = audioFilePath.replace(".mp3", ".wav");
            File outFile = new File(outFilePath);
            try {
                AudioAttributes audioAttributes = new AudioAttributes();
                audioAttributes.setCodec("pcm_s16le");
                audioAttributes.setBitRate(new Integer(128000));
                audioAttributes.setChannels(new Integer(2));
                audioAttributes.setSamplingRate(new Integer(44100));

                EncodingAttributes encodingAttributes = new EncodingAttributes();
                encodingAttributes.setFormat("wav");
                encodingAttributes.setAudioAttributes(audioAttributes);

                Encoder encoder = new Encoder();
                encoder.encode(inaudioFile, outFile, encodingAttributes);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return outFilePath;
        }
        if (filename.contains("wav")) {//默认转mp3
            String mp3FilePath = audioFilePath.replace(".wav", ".mp3");
            File outFile = new File(mp3FilePath);
            try {
                AudioAttributes audioAttributes = new AudioAttributes();
                audioAttributes.setCodec("libmp3lame");
                audioAttributes.setBitRate(new Integer(128080));
                audioAttributes.setChannels(new Integer(2));
                audioAttributes.setSamplingRate(new Integer(44100));

                EncodingAttributes encodingAttributes = new EncodingAttributes();
                encodingAttributes.setFormat("mp3");
                encodingAttributes.setAudioAttributes(audioAttributes);

                Encoder encoder = new Encoder();
                encoder.encode(inaudioFile, outFile, encodingAttributes);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return mp3FilePath;
        }
        return "";
    }

    /**
     * 音频添加背景音乐
     *
     * @par
     */
    public void mixAudio(String audioFolderpath) {
        List<File> audioList = FileUtil.loopFiles(audioFolderpath, file -> file.isFile());
        if (audioList == null || audioList.size() < 2) {
            throw new RuntimeException("音频添加背景乐无数据");
        }
        String audioFilePath = ""; // 音频文件路径
        String backgroundMusicPath = ""; // 背景音乐文件路径
        String outputFilePath = "";
        for (File file : audioList) {
            if (file.getName().contains("src")) {
                if (!file.getName().contains(".wav")) {
                    //将音频进行转换为wav
                    audioFilePath = converAudio(audioFilePath);
                } else {
                    audioFilePath = file.getAbsolutePath();
                }
            }
            if (file.getName().contains("back")) {
                if (!file.getName().contains(".mp3")) {
                    backgroundMusicPath = converAudio(backgroundMusicPath);
                } else {
                    backgroundMusicPath = file.getAbsolutePath();
                }
                outputFilePath = file.getAbsolutePath().replace(".", "_final.");
            }
        }
        AudioInputStream audioInputStream = null;
        AudioFormat audioFormat = null;
        SourceDataLine sourceDataLine = null;
        FileInputStream backgroundMusicInputStream = null;
        Player backgroundMusicPlayer = null;
        FileOutputStream outputStream = null;
        try {
            audioInputStream = AudioSystem.getAudioInputStream(new File(audioFilePath));
            audioFormat = getAudioFormat(audioInputStream);
            sourceDataLine = getSourceDataLine(audioFormat);

            backgroundMusicInputStream = new FileInputStream(backgroundMusicPath);
            backgroundMusicPlayer = new Player(backgroundMusicInputStream);
            // 开始播放背景音乐
            backgroundMusicPlayer.play();
            // 将音频内容写入到输出文件
            outputStream = new FileOutputStream(outputFilePath);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = audioInputStream.read(buffer)) != -1) {
                for (int i = 0; i < bytesRead; i++) {
                    outputStream.write(buffer[i]);
                }
                sourceDataLine.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // 停止并释放资源
            try {
                if (backgroundMusicPlayer != null) {
                    backgroundMusicPlayer.close();
                }
                if (sourceDataLine != null) {
                    sourceDataLine.drain();
                    sourceDataLine.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                if (audioInputStream != null) {
                    audioInputStream.close();
                }
                if (backgroundMusicInputStream != null) {
                    backgroundMusicInputStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 调整音量大小
     * ffmpeg -i input.mp3 -af "volume=0.1" output.mp3
     * <p>
     * ffmpeg -i input.mp3 -af "volume=10dB" output.mp3
     */
    public String controAudioVolume(String audiopath, float volume) throws Exception {
        File audioFile = new File(audiopath);
        String fileName = audioFile.getName();
        if (!audioFile.exists()) {
            throw new RuntimeException("文件不存在");
        }
        String outpath = audiopath.replace(".", "_final_hebing.");
        //生成str字幕文件
        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(audiopath);
        commands.add("-af");
        commands.add("\"volume=" + volume + "\"");
        commands.add(outpath);

        String result = FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(result);
        return outpath;
    }

    private AudioFormat getAudioFormat(AudioInputStream audioInputStream) throws IOException, UnsupportedAudioFileException {
        AudioFormat format = audioInputStream.getFormat();
        return new AudioFormat(
                format.getEncoding(),
                format.getSampleRate(),
                format.getSampleSizeInBits(),
                format.getChannels(),
                format.getFrameSize(),
                format.getFrameRate(),
                true);
    }

    private SourceDataLine getSourceDataLine(AudioFormat audioFormat) throws LineUnavailableException {
        SourceDataLine sourceDataLine = AudioSystem.getSourceDataLine(audioFormat);
        sourceDataLine.open(audioFormat);
        sourceDataLine.start();
        return sourceDataLine;
    }

    /**
     * 音频添加背景
     *
     * @return
     * @throws IOException
     */
    public String mixAudiosByPython(String filefolderpath) throws IOException {
        BufferedReader in = null;
        Process proc = null;
        StringBuffer buffer = new StringBuffer();
        try {
            URL resource = this.getClass().getClassLoader().getResource("voice.py");
            String path = resource.getPath();
            if (path.startsWith("/")) {
                path = path.substring(1);
            }
            String[] args = new String[]{"python", path, filefolderpath};
            proc = Runtime.getRuntime().exec(args);// 执行py文件

            in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line = null;

            while ((line = in.readLine()) != null) {
                buffer.append(line);
            }
            proc.waitFor();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (in != null) {
                in.close();
            }
            if (proc != null) {
                proc.destroy();
            }
        }
        return buffer.toString();
    }

    /**
     * 指定音频添加指定背景乐
     *
     * @return
     * @throws IOException
     */
    public String mixSingleAudio(String srcpath, String backpath) throws IOException {
        BufferedReader in = null;
        Process proc = null;
        StringBuffer buffer = new StringBuffer();
        try {
            URL resource = this.getClass().getClassLoader().getResource("singlevoice.py");
            String path = resource.getPath();
            if (path.startsWith("/")) {
                path = path.substring(1);
            }
            String[] args = new String[]{"python", path, srcpath, backpath};
            proc = Runtime.getRuntime().exec(args);// 执行py文件

            in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line = null;

            while ((line = in.readLine()) != null) {
                buffer.append(line);
            }
            proc.waitFor();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (in != null) {
                in.close();
            }
            if (proc != null) {
                proc.destroy();
            }
        }
        return srcpath.replace(".wav", "_final.wav");
    }

    /**
     * 指定音频添加指定背景乐,统一用wav无损模式处理音频
     * ffmpeg -i main_audio.mp3 -stream_loop -1 -i background_music.mp3 -filter_complex "[0:a][1:a]amix=inputs=2:duration=first" -c:a libmp3lame -qscale:a 2 output.mp3
     * ffmpeg -i main_audio.mp3 -i background_music.mp3 -filter_complex "[1:a]volume=0.5[a];[0:a][a]amix=inputs=2:duration=first" -c:a libmp3lame -qscale:a 2 output.mp3
     *
     * @throws IOException
     */
    public String mixSingleAudioByFFmpeg(String srcpath, String backpath) throws Exception {
        File audioFile = new File(srcpath);
        if (!audioFile.exists()) {
            throw new RuntimeException("主音频文件不存在");
        }
        File backFile = new File(backpath);
        if (!backFile.exists()) {
            throw new RuntimeException("背景音频文件不存在");
        }
        //格式统一转换为wav
        if (audioFile.getName().endsWith(".mp3")) {
            srcpath = converAudio(srcpath);
        }
        //格式统一转换为wav
        if (backFile.getName().endsWith(".mp3")) {
            backpath = converAudio(backpath);
        }
        String outpath = srcpath.replace(".", "_merge.");
        File outFile = new File(outpath);
        if (outFile.exists()) {
            outFile.delete();
        }
//        //获取原音频音量
//        float srcVolume= getAudioVolume(srcpath);
//        //获取相适应的背景音频音量
//        float lastVolume=srcVolume/VOLUMERATE;
//        //获取调整比率
//        float backVolume= getAudioVolume(backpath);
//        //rate
//        float rate=backVolume/lastVolume;
//        String lastRate=String.format("%.2f", rate);
//        System.out.println(lastRate);

        //合并音频
        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(srcpath);
        commands.add("-stream_loop");
        commands.add("-1");
        commands.add("-i");
        commands.add(backpath);
        commands.add("-filter_complex");
        commands.add("\"[1:a]volume=0.25[a];[0:a][a]amix=inputs=2:duration=first\"");
        commands.add("-c:a");
//        commands.add("libmp3lame");
        commands.add("pcm_s16le");//wav格式
        commands.add("-qscale:a");
        commands.add("2");
        commands.add(outpath);

        String result = FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(result);

        return outpath;
    }

    /**
     * 获取音频的平均音量和最大音量
     * ffmpeg -i src.wav -filter_complex volumedetect -c:v copy -f null /dev/null
     */
    public float getAudioVolume(String srcpath) throws IOException {
        File audioFile = new File(srcpath);
        if (!audioFile.exists()) {
            throw new RuntimeException("主音频文件不存在");
        }
        //格式统一转换为wav
        if (audioFile.getName().endsWith(".mp3")) {
            srcpath = converAudio(srcpath);
        }
        //合并音频
        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(srcpath);
        commands.add("-filter_complex");
        commands.add("volumedetect");
        commands.add("-c:v");
        commands.add("copy");
        commands.add("-f");
        commands.add("null");
        commands.add("/dev/null");

        InputStream errorStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader br = null;
        String db = "";
        try {
            ProcessBuilder builder = new ProcessBuilder(commands);
            Process process = builder.start();
            errorStream = process.getErrorStream();
            inputStreamReader = new InputStreamReader(errorStream);
            br = new BufferedReader(inputStreamReader);
            while ((db = br.readLine()) != null) {
                if (db.contains("max_volume")) {
                    db = db.split(": ")[1];
                    db = db.split(" ")[0];
                    break;
                }
            }
        } finally {
            br.close();
            inputStreamReader.close();
            errorStream.close();
        }
        float resValue = Float.valueOf(db) * (-1);

        return resValue;
    }

    /**
     * 默认将语言训练模型放置在d盘whisper文件夹
     * 音频转字幕文件
     * whisper C:\Users\Administrator\Desktop\whisper\teng.mp3 --model small --model_dir D:\whisper --language Chinese
     */
    public String audioToSrt(String audioFilePath) throws Exception {
        File audioFile = new File(audioFilePath);
        String fileName = audioFile.getName();
        if (!audioFile.exists()) {
            throw new RuntimeException("文件不存在");
        }
        //生成str字幕文件
        List<String> commands = new ArrayList<>();
        commands.add("whisper");
        commands.add(audioFilePath);
        commands.add("--model");
        commands.add("medium");//medium  small
        commands.add("--model_dir");
        commands.add("D:\\whisper");
        commands.add("--language");
        commands.add("Chinese");

//        newRunCommand(commands);

        String result = FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(result);
        //获取当前终端命令行路径
        Path currentWorkingDirectory = Paths.get("");
        String newsrtFilename = "";
        if (fileName.endsWith(".mp3")) {
            newsrtFilename = fileName.replace(".mp3", ".srt");
        }
        if (fileName.endsWith(".wav")) {
            newsrtFilename = fileName.replace(".wav", ".srt");
        }
        String sourcePath = currentWorkingDirectory.toAbsolutePath().toString() + File.separator + newsrtFilename;
        System.out.println("当前项目路径：" + sourcePath);
        //移动文件
        Path target = null;
        try {
            Path source = Paths.get(sourcePath);
            if (audioFilePath.endsWith(".mp3")) {
                target = Paths.get(audioFilePath.replace(".mp3", ".srt"));
            }
            if (audioFilePath.endsWith(".wav")) {
                target = Paths.get(audioFilePath.replace(".wav", ".srt"));
            }
            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
            //筛选相同文件名的文件
            List<File> audioList = FileUtil.loopFiles(currentWorkingDirectory.toAbsolutePath().toString(), file -> file.isFile() && file.getName().startsWith(fileName.substring(0, fileName.indexOf("."))));
            //删除字幕文件
            for (File file : audioList) {
                file.delete();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
        }
        return target.toFile().getAbsolutePath();
    }

    /**
     * 音频转字幕文件:通过静音位置进行处理
     * ffmpeg -i input.wav -af silencedetect=-60dB:d=0.5 -f null -
     */
    public String audioToSrtBySilence(String audioFilePath) throws Exception {
        File audioFile = new File(audioFilePath);
        String fileName = audioFile.getName();
        if (!audioFile.exists()) {
            throw new RuntimeException("音频不存在");
        }
        //获取txt文件
        List<File> txtList = FileUtil.loopFiles(audioFile.getParent(), file -> file.isFile() && file.getName().endsWith(".txt"));
        if (txtList==null||txtList.isEmpty()) {
            throw new RuntimeException("文本不存在");
        }
        //生成str字幕文件
        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(audioFilePath);
        commands.add("-af");
        commands.add("silencedetect=-60dB:d=0.5");//medium  small
        commands.add("-f");
        commands.add("null");
        commands.add("-");

        String result = FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(result);
        //解析返回参数并生成参数
        Map<Integer,String> silenceMap=new HashMap<>();
        String[] endstrs=result.split("silence_start");
        int index=0;
        for(String str:endstrs){
            if(str.contains("silence_end:")){
                String endtiem=str.substring(str.indexOf("silence_end:")+12,str.indexOf("|")).trim();
                endtiem=Float.valueOf(endtiem)*1000+"";
                if(endtiem.contains(".")){
                    endtiem=endtiem.substring(0,endtiem.indexOf("."));
                }
                silenceMap.put(index,endtiem);
                System.out.println("结束时间："+(Integer.valueOf(endtiem)/1000));
                index++;
            }
        }
        System.out.println("次数："+index);
        String resPath= new HandleSpeechService().createSrtBySilence(txtList.get(0).getAbsolutePath(),silenceMap);
        return resPath;
    }

    /**
     * 音频转字幕文件:通过静音位置进行处理
     * ffmpeg -i input.wav -af silencedetect=-60dB:d=0.5 -f null -
     */
    public String generateSrtBySilence(String audioFilePath,int fontlength) throws Exception {
        File audioFile = new File(audioFilePath);
        if (!audioFile.exists()) {
            throw new RuntimeException("音频不存在");
        }
        //获取txt文件
        List<File> txtList = FileUtil.loopFiles(audioFile.getParent(), file -> file.isFile() && file.getName().endsWith(".txt")&&!file.getName().contains("part"));
        if (txtList==null||txtList.isEmpty()) {
            throw new RuntimeException("文本不存在");
        }
        //生成str字幕文件
        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(audioFilePath);
        commands.add("-af");
        commands.add("silencedetect=-60dB:d=0.5");//medium  small
        commands.add("-f");
        commands.add("null");
        commands.add("-");

        String result = FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(result);
        //解析返回参数并生成参数
        Map<Integer,String> silenceMap=new HashMap<>();
        String[] endstrs=result.split("silence_start");
        List<String> endtimeList=new ArrayList<>();
        for(String str:endstrs){
            if(str.contains("silence_end:")){
                String endtiem=str.substring(str.indexOf("silence_end:")+12,str.indexOf("|")).trim();
                endtiem=Float.valueOf(endtiem)*1000+"";
                if(endtiem.contains(".")){
                    endtiem=endtiem.substring(0,endtiem.indexOf("."));
                }
                endtimeList.add(endtiem);
                System.out.println("结束时间："+(Integer.valueOf(endtiem)/1000));
            }
        }
        for(int i=0;i<endtimeList.size();i++){
            silenceMap.put(i,endtimeList.get(i));
        }
        String resPath= new HandleSpeechService().createSrtByFFmpegSilence(txtList.get(0).getAbsolutePath(),silenceMap,fontlength);
        return resPath;
    }

    /**
     * 音频转字幕文件:通过静音位置进行处理
     * ffmpeg -i input.wav -af silencedetect=-60dB:d=0.5 -f null -
     */
    public String generateSrtBySilence(String audioFilePath,String txtpath,int fontlength) throws Exception {
        File audioFile = new File(audioFilePath);
        if (!audioFile.exists()) {
            throw new RuntimeException("音频不存在");
        }
        //获取txt文件
        File file=new File(txtpath);
        if (!file.exists()) {
            throw new RuntimeException("文本不存在");
        }
        //生成str字幕文件
        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(audioFilePath);
        commands.add("-af");
        commands.add("silencedetect=-60dB:d=0.5");//medium  small
        commands.add("-f");
        commands.add("null");
        commands.add("-");

        String result = FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(result);
        //解析返回参数并生成参数
        Map<Integer,String> silenceMap=new HashMap<>();
        String[] endstrs=result.split("silence_start");
        List<String> endtimeList=new ArrayList<>();
        for(String str:endstrs){
            if(str.contains("silence_end:")){
                String endtiem=str.substring(str.indexOf("silence_end:")+12,str.indexOf("|")).trim();
                endtiem=Float.valueOf(endtiem)*1000+"";
                if(endtiem.contains(".")){
                    endtiem=endtiem.substring(0,endtiem.indexOf("."));
                }
                endtimeList.add(endtiem);
                System.out.println("结束时间："+(Integer.valueOf(endtiem)/1000));
            }
        }
        for(int i=0;i<endtimeList.size();i++){
            silenceMap.put(i,endtimeList.get(i));
        }
        String resPath= new HandleSpeechService().createSrtByFFmpegSilence(txtpath,silenceMap,fontlength);
        return resPath;
    }

    /**
     * 音频添加背景乐并生成字幕文件(音量默认0.1)
     *
     */
    public Map<String, String> mergeAudioAndBackBySrt(String srcaudiopath, String backpath) throws Exception {
        String srcinitaudiopath = srcaudiopath;
        Map<String, String> resMap = new HashMap<>();
        File audioFile = new File(srcaudiopath);
        if (!audioFile.exists()) {
            throw new RuntimeException("源音频不存在");
        }
        File backFile = new File(backpath);
        if (!backFile.exists()) {
            throw new RuntimeException("背景音频不存在");
        }
        FFmpegFrameGrabber grabber = null;
        long durationInSec = 0l;
        try {
            grabber = new FFmpegFrameGrabber(srcaudiopath);
            grabber.start();
            durationInSec = grabber.getFormatContext().duration() / 1000000;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            grabber.release();
            grabber.close();
        }
        //格式统一转换为wav
        if (audioFile.getName().endsWith(".mp3")) {
            srcaudiopath = converAudio(srcaudiopath);
        }
        try {
            //合成音频通过ffmpeg
            String finalaudio = mixSingleAudioByFFmpeg(srcaudiopath, backpath);
            resMap.put("audio", finalaudio);
            //源音频生成字幕文件
            String srtpath = audioToSrt(srcinitaudiopath);
            List<File> srctxtList = FileUtil.loopFiles(audioFile.getParent(), file -> file.isFile() && file.getName().endsWith(".txt"));
            if (srctxtList == null || srctxtList.size() <= 0) {
                throw new RuntimeException("字幕源文件不存在");
            }
            try {
                String finalsrt = new HandleSpeechService().handleSrtByMulMethods(srctxtList.get(0).getAbsolutePath(), srtpath);
                resMap.put("srt", finalsrt);
            } catch (Exception e) {
                System.out.println(e.toString());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            grabber.release();
            grabber.close();
        }
        return resMap;
    }

    /**
     * 音频添加背景乐并生成字幕文件(音量默认0.1)
     */
    public Map<String, String> mergeAudioAndBackBySrtAndTag(String srcaudiopath, String backpath) throws Exception {
        Map<String, String> resMap = new HashMap<>();
        File audioFile = new File(srcaudiopath);
        if (!audioFile.exists()) {
            throw new RuntimeException("源音频不存在");
        }
        File backFile = new File(backpath);
        if (!backFile.exists()) {
            throw new RuntimeException("背景音频不存在");
        }
        FFmpegFrameGrabber grabber = null;
        long durationInSec = 0l;
        try {
            grabber = new FFmpegFrameGrabber(srcaudiopath);
            grabber.start();
            durationInSec = grabber.getFormatContext().duration() / 1000000;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            grabber.release();
            grabber.close();
        }
        //统一转为wav无损模式
        if (audioFile.getName().endsWith(".mp3")) {
            srcaudiopath = converAudio(srcaudiopath);
        }
        try {
            //源音频生成字幕文件
            String finalsrt = audioToSrtBySilence(srcaudiopath);
            resMap.put("srt", finalsrt);
            //添加前缀
            String prefixaudio = new VedioUtils().mergePrefix2Audio(srcaudiopath);
            //合成音频根据ffmpeg
            String finalaudio = mixSingleAudioByFFmpeg(prefixaudio, backpath);
            //调大音量4倍
            String finaleVolumeAudio=controAudioVolume(finalaudio,5f);
            resMap.put("audio", finaleVolumeAudio);
            List<File> srctxtList = FileUtil.loopFiles(audioFile.getParent(), file -> file.isFile() && file.getName().endsWith(".txt"));
            if (srctxtList == null || srctxtList.size() <= 0) {
                throw new RuntimeException("字幕源文件不存在");
            }
            File prefixaudiofile = new File(prefixaudio);
            if (prefixaudiofile.exists()) {
                prefixaudiofile.delete();
            }
            File srcaudiopathfile = new File(srcaudiopath.replace(".wav", ".mp3"));
            if (srcaudiopathfile.exists()) {
                srcaudiopathfile.delete();
            }
            File finalaudiofile = new File(finalaudio);
            if (finalaudiofile.exists()) {
                finalaudiofile.delete();
            }
            File backpathfile = new File(backpath.replace(".wav",".mp3"));
            if (backpathfile.exists()) {
                backpathfile.delete();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            grabber.release();
            grabber.close();
        }
        return resMap;
    }

    /**
     * 设置指定音频的长度
     * @param audiopath
     * @param duation
     */
    public void extendAudio(String audiopath, String duation) throws Exception {
    //获取音频原始时长
        FFmpegFrameGrabber grabberVideo = null;
        int durationAudio=0;
        int total=Integer.valueOf(duation);
        try {
            //抓取视频帧
            grabberVideo = new FFmpegFrameGrabber(audiopath);
            grabberVideo.start();
            //获取时长,以短的文件为主进行截取
            String resdura = grabberVideo.getFormatContext().duration() / 1000000+"";

            durationAudio=  Integer.valueOf(resdura);

        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            grabberVideo.release();
            grabberVideo.stop();
        }
        int circle=total/durationAudio+1;
        if(audiopath.endsWith(".mp3")){
            audiopath=new HandleAudioService().converAudio(audiopath);
        }
        String finalMp3Path=audiopath.replace(".wav","_final.wav");

        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-stream_loop");
        commands.add(circle+"");
        commands.add("-i");
        commands.add(audiopath);
        commands.add("-c");
        commands.add("copy");
        commands.add(finalMp3Path);

        String res=FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(res);
        //视频生成完毕后进行截取
        //将5分钟转化为时分秒
        int hours=total/3600;
        int minus=(total%3600)/60;
        int second=total-hours*3600-minus*60;
        StringBuffer buffer=new StringBuffer();
        if(hours<10){
            buffer.append("0"+hours);
        }else{
            buffer.append(""+hours);
        }
        buffer.append(":");
        if(minus<10){
            buffer.append("0"+minus);
        }else{
            buffer.append(""+minus);
        }
        buffer.append(":");
        if(second<10){
            buffer.append("0"+second);
        }else{
            buffer.append(""+second);
        }

        new HandleAudioService().cutAudio(finalMp3Path, "00:00:00",buffer.toString());
        File oldFile=new File(finalMp3Path);
        if(oldFile.exists()){
            oldFile.delete();
        }

    }



}
